"""
Health Check Service
健康检查服务 - 系统组件健康状态监控
"""

import asyncio
import aiohttp
from typing import Dict, Any, List
from datetime import datetime
import structlog

from ..core.config import settings
from ..core.database import check_db_connection, get_db
from ..core.task_queue import task_queue
from ..services.ai_model_service import AIModelService

# 配置结构化日志
logger = structlog.get_logger(__name__)


class HealthCheckService:
    """健康检查服务类"""
    
    def __init__(self):
        self.ai_service = AIModelService()
        self.checks = {
            "database": self._check_database,
            "task_queue": self._check_task_queue,
            "ai_providers": self._check_ai_providers,
            "storage": self._check_storage,
            "memory": self._check_memory,
        }
    
    async def get_health_status(self) -> Dict[str, Any]:
        """
        获取系统健康状态
        
        Returns:
            Dict[str, Any]: 健康状态信息
        """
        start_time = datetime.now()
        
        try:
            # 并行执行所有健康检查
            check_results = await asyncio.gather(
                *[
                    self._run_health_check(name, check_func)
                    for name, check_func in self.checks.items()
                ],
                return_exceptions=True
            )
            
            # 构建健康状态
            health_status = {
                "status": "healthy",
                "timestamp": datetime.now().isoformat(),
                "checks": {},
                "overall_health": True,
            }
            
            overall_healthy = True
            
            for i, (check_name, _) in enumerate(self.checks.items()):
                result = check_results[i]
                
                if isinstance(result, Exception):
                    # 检查失败
                    health_status["checks"][check_name] = {
                        "status": "unhealthy",
                        "error": str(result),
                        "checked_at": datetime.now().isoformat(),
                    }
                    overall_healthy = False
                else:
                    health_status["checks"][check_name] = result
                    if result.get("status") != "healthy":
                        overall_healthy = False
            
            # 设置总体状态
            health_status["overall_health"] = overall_healthy
            health_status["status"] = "healthy" if overall_healthy else "unhealthy"
            
            # 添加检查耗时
            check_duration = (datetime.now() - start_time).total_seconds()
            health_status["check_duration_seconds"] = round(check_duration, 3)
            
            logger.info(
                "Health check completed",
                overall_health=overall_healthy,
                check_duration=check_duration,
                total_checks=len(self.checks)
            )
            
            return health_status
            
        except Exception as e:
            logger.error("Health check failed", error=str(e))
            return {
                "status": "unhealthy",
                "timestamp": datetime.now().isoformat(),
                "error": str(e),
                "overall_health": False,
                "checks": {},
            }
    
    async def _run_health_check(self, name: str, check_func) -> Dict[str, Any]:
        """运行单个健康检查"""
        try:
            logger.debug(f"Running health check: {name}")
            result = await check_func()
            logger.debug(f"Health check completed: {name}", status=result.get("status"))
            return result
        except Exception as e:
            logger.error(f"Health check failed: {name}", error=str(e))
            raise e
    
    async def _check_database(self) -> Dict[str, Any]:
        """检查数据库健康状态"""
        try:
            # 检查数据库连接
            connection_healthy = await check_db_connection()
            
            # 获取数据库统计信息
            db_stats = {
                "connection_healthy": connection_healthy,
                "connection_pool_size": settings.database.pool_size,
                "max_overflow": settings.database.max_overflow,
            }
            
            if connection_healthy:
                # 尝试执行简单查询
                try:
                    async for db in get_db():
                        result = await db.execute("SELECT 1")
                        await db.close()
                        
                    db_stats["query_test"] = "passed"
                    status = "healthy"
                    
                except Exception as e:
                    db_stats["query_test"] = "failed"
                    db_stats["query_error"] = str(e)
                    status = "unhealthy"
            else:
                status = "unhealthy"
            
            return {
                "status": status,
                "checked_at": datetime.now().isoformat(),
                "details": db_stats,
            }
            
        except Exception as e:
            return {
                "status": "unhealthy",
                "checked_at": datetime.now().isoformat(),
                "error": str(e),
            }
    
    async def _check_task_queue(self) -> Dict[str, Any]:
        """检查任务队列健康状态"""
        try:
            queue_stats = task_queue.get_stats()
            
            # 检查队列是否运行
            is_running = queue_stats.get("is_running", False)
            pending_tasks = queue_stats.get("pending", 0)
            processing_tasks = queue_stats.get("processing", 0)
            
            # 如果队列未运行但有待处理任务，则为不健康
            if not is_running and (pending_tasks > 0 or processing_tasks > 0):
                status = "unhealthy"
            elif pending_tasks > settings.task_queue.max_tasks * 0.8:  # 80%容量警告
                status = "warning"
            else:
                status = "healthy"
            
            return {
                "status": status,
                "checked_at": datetime.now().isoformat(),
                "details": {
                    "is_running": is_running,
                    "pending_tasks": pending_tasks,
                    "processing_tasks": processing_tasks,
                    "completed_tasks": queue_stats.get("completed", 0),
                    "failed_tasks": queue_stats.get("failed", 0),
                    "max_tasks": settings.task_queue.max_tasks,
                    "worker_count": settings.task_queue.max_workers,
                },
            }
            
        except Exception as e:
            return {
                "status": "unhealthy",
                "checked_at": datetime.now().isoformat(),
                "error": str(e),
            }
    
    async def _check_ai_providers(self) -> Dict[str, Any]:
        """检查AI提供商健康状态"""
        try:
            providers = {
                "doubao": {
                    "enabled": bool(settings.ai_provider.ark_api_key),
                    "base_url": settings.ai_provider.ark_base_url,
                },
                "ali": {
                    "enabled": bool(settings.ai_provider.ali_api_key),
                    "base_url": settings.ai_provider.ali_base_url,
                },
                "openai": {
                    "enabled": bool(settings.ai_provider.openai_api_key),
                    "base_url": "https://api.openai.com/v1",
                },
            }
            
            provider_statuses = {}
            overall_healthy = True
            
            for provider_name, provider_config in providers.items():
                if not provider_config["enabled"]:
                    provider_statuses[provider_name] = {
                        "status": "disabled",
                        "message": "API密钥未配置",
                    }
                    continue
                
                # 检查提供商连接
                try:
                    # 尝试简单的API调用或连接测试
                    is_healthy = await self._test_ai_provider_connection(provider_name)
                    
                    if is_healthy:
                        provider_statuses[provider_name] = {
                            "status": "healthy",
                            "base_url": provider_config["base_url"],
                            "checked_at": datetime.now().isoformat(),
                        }
                    else:
                        provider_statuses[provider_name] = {
                            "status": "unhealthy",
                            "base_url": provider_config["base_url"],
                            "message": "连接测试失败",
                        }
                        overall_healthy = False
                        
                except Exception as e:
                    provider_statuses[provider_name] = {
                        "status": "unhealthy",
                        "base_url": provider_config["base_url"],
                        "error": str(e),
                    }
                    overall_healthy = False
            
            return {
                "status": "healthy" if overall_healthy else "unhealthy",
                "checked_at": datetime.now().isoformat(),
                "details": provider_statuses,
            }
            
        except Exception as e:
            return {
                "status": "unhealthy",
                "checked_at": datetime.now().isoformat(),
                "error": str(e),
            }
    
    async def _check_storage(self) -> Dict[str, Any]:
        """检查存储健康状态"""
        try:
            import shutil
            import os
            
            # 检查上传目录
            upload_dir = Path(settings.file_storage.upload_dir)
            upload_dir_exists = upload_dir.exists()
            upload_dir_writable = os.access(upload_dir, os.W_OK) if upload_dir_exists else False
            
            # 检查内容存储目录
            content_dir = Path(settings.file_storage.content_storage_path)
            content_dir_exists = content_dir.exists()
            content_dir_writable = os.access(content_dir, os.W_OK) if content_dir_exists else False
            
            # 检查磁盘空间
            if upload_dir_exists:
                upload_disk_usage = shutil.disk_usage(upload_dir)
                upload_free_gb = upload_disk_usage.free / (1024**3)
                upload_usage_percent = (upload_disk_usage.used / upload_disk_usage.total) * 100
            else:
                upload_free_gb = 0
                upload_usage_percent = 0
            
            # 判断状态
            if not upload_dir_exists or not upload_dir_writable:
                status = "unhealthy"
            elif upload_usage_percent > 90:  # 磁盘使用率超过90%
                status = "warning"
            elif upload_free_gb < 1:  # 剩余空间少于1GB
                status = "warning"
            else:
                status = "healthy"
            
            return {
                "status": status,
                "checked_at": datetime.now().isoformat(),
                "details": {
                    "upload_directory": {
                        "exists": upload_dir_exists,
                        "writable": upload_dir_writable,
                        "path": str(upload_dir),
                    },
                    "content_directory": {
                        "exists": content_dir_exists,
                        "writable": content_dir_writable,
                        "path": str(content_dir),
                    },
                    "disk_usage": {
                        "free_gb": round(upload_free_gb, 2),
                        "usage_percent": round(upload_usage_percent, 2),
                    },
                },
            }
            
        except Exception as e:
            return {
                "status": "unhealthy",
                "checked_at": datetime.now().isoformat(),
                "error": str(e),
            }
    
    async def _check_memory(self) -> Dict[str, Any]:
        """检查内存使用状态"""
        try:
            import psutil
            
            # 获取内存使用情况
            memory = psutil.virtual_memory()
            memory_percent = memory.percent
            memory_available_gb = memory.available / (1024**3)
            
            # 获取交换空间使用情况
            swap = psutil.swap_memory()
            swap_percent = swap.percent
            
            # 判断状态
            if memory_percent > 90:  # 内存使用率超过90%
                status = "warning"
            elif memory_available_gb < 0.5:  # 可用内存少于500MB
                status = "warning"
            elif swap_percent > 80:  # 交换空间使用率超过80%
                status = "warning"
            else:
                status = "healthy"
            
            return {
                "status": status,
                "checked_at": datetime.now().isoformat(),
                "details": {
                    "memory": {
                        "total_gb": round(memory.total / (1024**3), 2),
                        "available_gb": round(memory_available_gb, 2),
                        "used_percent": round(memory_percent, 2),
                        "used_gb": round(memory.used / (1024**3), 2),
                    },
                    "swap": {
                        "total_gb": round(swap.total / (1024**3), 2),
                        "used_gb": round(swap.used / (1024**3), 2),
                        "used_percent": round(swap_percent, 2),
                    },
                },
            }
            
        except ImportError:
            return {
                "status": "unknown",
                "checked_at": datetime.now().isoformat(),
                "message": "psutil模块未安装，无法检查内存状态",
            }
        except Exception as e:
            return {
                "status": "unhealthy",
                "checked_at": datetime.now().isoformat(),
                "error": str(e),
            }
    
    async def _test_ai_provider_connection(self, provider_name: str) -> bool:
        """测试AI提供商连接"""
        try:
            # 尝试进行简单的API调用
            test_prompt = "Hello, this is a connection test."
            
            if provider_name == "doubao":
                # 豆包连接测试
                test_result = await self.ai_service.test_connection("doubao")
            elif provider_name == "ali":
                # 阿里云连接测试
                test_result = await self.ai_service.test_connection("ali")
            elif provider_name == "openai":
                # OpenAI连接测试
                test_result = await self.ai_service.test_connection("openai")
            else:
                return False
            
            return test_result.get("success", False)
            
        except Exception as e:
            logger.error(f"AI provider connection test failed: {provider_name}", error=str(e))
            return False
    
    async def get_detailed_health_report(self) -> Dict[str, Any]:
        """获取详细的健康报告"""
        basic_health = await self.get_health_status()
        
        # 添加额外的系统信息
        detailed_report = {
            **basic_health,
            "system_info": {
                "app_name": settings.app_name,
                "app_version": settings.app_version,
                "app_env": settings.app_env,
                "python_version": "3.11+",  # 可以根据实际版本调整
                "platform": "linux",  # 可以根据实际平台调整
            },
            "recommendations": await self._generate_health_recommendations(basic_health),
        }
        
        return detailed_report
    
    async def _generate_health_recommendations(self, health_status: Dict[str, Any]) -> List[str]:
        """生成健康建议"""
        recommendations = []
        
        checks = health_status.get("checks", {})
        
        # 数据库健康建议
        db_check = checks.get("database", {})
        if db_check.get("status") != "healthy":
            recommendations.append("检查数据库连接配置和网络连接")
        
        # 任务队列健康建议
        queue_check = checks.get("task_queue", {})
        if queue_check.get("status") == "warning":
            pending_tasks = queue_check.get("details", {}).get("pending_tasks", 0)
            if pending_tasks > 500:
                recommendations.append("任务队列积压严重，建议增加工作协程数或优化任务处理")
        
        # AI提供商健康建议
        ai_check = checks.get("ai_providers", {})
        if ai_check.get("status") != "healthy":
            ai_details = ai_check.get("details", {})
            unhealthy_providers = [
                name for name, detail in ai_details.items()
                if detail.get("status") == "unhealthy"
            ]
            if unhealthy_providers:
                recommendations.append(f"检查以下AI提供商配置: {', '.join(unhealthy_providers)}")
        
        # 存储健康建议
        storage_check = checks.get("storage", {})
        if storage_check.get("status") == "warning":
            disk_details = storage_check.get("details", {}).get("disk_usage", {})
            if disk_details.get("usage_percent", 0) > 85:
                recommendations.append("磁盘空间使用率较高，建议清理旧文件或扩容")
        
        # 内存健康建议
        memory_check = checks.get("memory", {})
        if memory_check.get("status") == "warning":
            memory_details = memory_check.get("details", {}).get("memory", {})
            if memory_details.get("used_percent", 0) > 85:
                recommendations.append("内存使用率较高，建议优化应用或增加内存")
        
        if not recommendations:
            recommendations.append("系统运行正常，继续保持监控")
        
        return recommendations


# 全局健康检查服务实例
health_check_service = HealthCheckService()

# 导出
__all__ = ["HealthCheckService", "health_check_service"]